package org.example.service.impl;


import cn.hutool.core.bean.BeanUtil;
import net.sf.jsqlparser.expression.operators.arithmetic.Concat;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.example.constant.MessageConstant;
import org.example.constant.StatusConstant;
import org.example.domain.StockLog;
import org.example.dto.StockLogDto;
import org.example.exception.NumberErrorException;
import org.example.mapper.StockLogMapper;
import org.example.service.StockLogService;
import org.example.utils.SnowFlake;
import org.example.vo.StockExcelVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.InputStream;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.temporal.ChronoUnit;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * @author SweetPig
 * @description 针对表【stock_log】的数据库操作Service实现
 * @createDate 2024-06-03 11:25:54
 */
@Service
public class StockLogServiceImpl implements StockLogService {

    @Autowired
    private StockLogMapper stockLogMapper;

    /**
     * 仓库盘点记录
     *
     * @param stockLogDto
     */
    public void stockLog(StockLogDto stockLogDto) {
        StockLog stockLog = fillStockLog(stockLogDto);
        stockLogMapper.insertStockLog(stockLog);
    }

    /**
     * 导出盘点数据
     *
     * @param response
     */
    public void exportExcel(HttpServletResponse response, String warehouseName) {
        response.setHeader("Content-Disposition", "attachment;filename=" + "title_".concat(warehouseName).concat(".xlsx"));
        response.setContentType("application/vnd.ms-excel;charset=utf-8");
        int rowNum = 0;
        //1. 查询数据库，获取盘点数据---查询最近30天的盘点数据
        LocalDate dateBegin = LocalDate.now().minusDays(29);
        LocalDate dateEnd = LocalDate.now();
        //查询概览数据
        StockExcelVo stockExcelVo = getStockData(LocalDateTime.of(dateBegin, LocalTime.MIN), LocalDateTime.of(dateEnd, LocalTime.MAX));
        //通过POI将数据写如Excel中
        InputStream resourceAsStream = this.getClass().getClassLoader()
                .getResourceAsStream("excel/盘点数据报表模板.xlsx");
        try {
            //基于模板文件创建一个新的Excel文件
            assert resourceAsStream != null;
            XSSFWorkbook excel = new XSSFWorkbook(resourceAsStream);
            //获取表格文件的sheet页
            XSSFSheet sheet = excel.getSheet("Sheet1");
            //填充数据 时间
            sheet.getRow(1).getCell(1).setCellValue("时间:" + dateBegin + "至" + dateEnd);
            //获得第4行
            XSSFRow row = sheet.getRow(3);
            row.getCell(2).setCellValue(warehouseName);
            row.getCell(4).setCellValue(stockExcelVo.getStockCompletionRate());
            row.getCell(6).setCellValue(stockExcelVo.getValidStockCount());
            //填充明细数据
            for (int i = 0; i < 30; i++) {
                LocalDate date = dateBegin.plusDays(i);
                //查询某一天的盘点数据
                List<StockLog> stockLogs = FillStockData(LocalDateTime.of(date, LocalTime.MIN), LocalDateTime.of(date, LocalTime.MAX), warehouseName);
                //获得某一行
                for (StockLog stockLog : stockLogs) {
                    System.err.println("数据:" + stockLog);
                    row = sheet.getRow(7 +  rowNum++);
                    row.getCell(1).setCellValue(String.valueOf(date));//日期
                    row.getCell(2).setCellValue(stockLog.getDepositId().substring(4)+"***");//仓储位置ID
                    row.getCell(3).setCellValue(stockLog.getWarehouseNum());//记录数
                    row.getCell(4).setCellValue(stockLog.getCropName());//作物名称
                    row.getCell(5).setCellValue(stockLog.getStockCapacity());//盘点数量
                    row.getCell(6).setCellValue(Objects.equals(stockLog.getStockStatus(), StatusConstant.ENABLE) ? "正常" : "异常");//状态
                }
            }
            //3. 通过输出流将Excel文件下载到客户端浏览器
            ServletOutputStream out = response.getOutputStream();
            excel.write(out);
            //关闭资源
            out.close();
            excel.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public List<StockLog> FillStockData(LocalDateTime begin, LocalDateTime end, String warehouseName) {
        Map<String, Object> map = new HashMap<>();
        map.put("warehouseName", warehouseName);
        map.put("begin", begin);
        map.put("end", end);
        //查询总盘点明细
        return stockLogMapper.getOneByMap(map);
    }

    /**
     * 根据时间段统计盘点数据
     *
     * @param begin
     * @param end
     * @return
     */
    public StockExcelVo getStockData(LocalDateTime begin, LocalDateTime end) {
        Map<String, Object> map = new HashMap<>();
        map.put("begin", begin);
        map.put("end", end);
        //查询总盘点明细
        List<StockLog> stockLogs = stockLogMapper.getOneByMap(map);
        int validStockCount = stockLogs.size();
        //异常盘点
        List<StockLog> collect = stockLogs.stream().filter(
                m -> Objects.equals(m.getStockStatus(), StatusConstant.DISABLE)
        ).collect(Collectors.toList());
        //异常盘点的数量
        int validOrderCount = collect.size();

        double stockCompletionRate = 0.0;
        if (validStockCount != 0 && validOrderCount != 0) {
            //盘点异常率
            stockCompletionRate = (double) validOrderCount / validStockCount;
        }
        return StockExcelVo.builder()
                .validStockCount(validStockCount)
                .stockCompletionRate(stockCompletionRate)
                .build();
    }

    /**
     * 填充盘点记录
     *
     * @param stockLogDto
     * @return
     */
    private StockLog fillStockLog(StockLogDto stockLogDto) {
        int status = StatusConstant.DISABLE;
        if (stockLogDto.getStockCapacity() == null) {
            throw new NumberErrorException(MessageConstant.INPUT_CAPACITY_ERROR);
        }
        if (Objects.equals(stockLogDto.getStockCapacity(), stockLogDto.getWarehousingNum())) {
            status = StatusConstant.ENABLE;
        }
        StockLog stockLog = BeanUtil.copyProperties(stockLogDto, StockLog.class);
        stockLog.setWarehouseNum(stockLogDto.getWarehousingNum());
        stockLog.setId(String.valueOf(new SnowFlake().nextId()));
        stockLog.setDepositId(stockLogDto.getId());
        stockLog.setStockStatus(status);
        stockLog.setStockLogTime(LocalDateTime.now());
        return stockLog;
    }

}




